package com.sinochem.iot.rule.utils;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("unchecked")
@Component
public class RedisUtil {
	private static Logger logger = LoggerFactory.getLogger(RedisUtil.class);
	private static RedisTemplate redisTemplate;

	public static RedisTemplate getRedisTemplate(){
		return redisTemplate;
	}
	/**
	 * 从redis中获取字符串
	 * @param key
	 * @return
	 */
	public static String getString(String key){
		try{
			return (String)getObject(key);
		}catch (Exception e){
			logger.error("Failed to get a string from the redis,key="+key,e);
		}
		return null;
	}
	/**
	 * 设置字符串
	 * @param key redis key
	 * @param value 值
	 */
	public static void setString(String key,String value){
		setObject(key, value);
	}
	/**
	 * 设置带有效时间的字符串到redis中
	 * @param key redis key
	 * @param value 值
	 * @param validTime 有效时间，单位秒
	 */
	public static void setString(String key,String value,long validTime){
		setObject(key, value, validTime);
	}
	/**
	 * 从redis中获取对象
	 * @param key redis key
	 * @return
	 */
	public static Object getObject(String key){
		try{
			return getRedisTemplate().opsForValue().get(key);
		}catch(Exception e){
			logger.error("Failed to get the object from the redis,key="+key,e);
		}
		return null;
	}

	/**
	 * 从redis中获取对象
	 * @param key redis key
	 * @param clz 返回值类型的class
	 * @param <T> 返回值类型
	 * @return
	 */
	public static <T> T getObject(String key,Class<T> clz){
		try{
			return (T)getRedisTemplate().opsForValue().get(key);
		}catch(Exception e){
			logger.error("Failed to get the object from the redis,key="+key,e);
		}
		return null;
	}
	/**
	 * 设置对象
	 * @param key redis key
	 * @param value 值
	 */
	public static void setObject(String key,Object value){
		try{
			getRedisTemplate().opsForValue().set(key, value);
		}catch(Exception e){
			logger.error("Setting the redis object failed,key="+key+"  value="+JSON.toJSONString(value),e);
		}
	}
	/**
	 * 设置带有效时间的对象到redis中
	 * @param key redis key
	 * @param value 值
	 * @param validTime 有效时间，单位秒
	 */
	public static void setObject(String key,Object value,long validTime){
		setObject(key, value, validTime, TimeUnit.SECONDS);
	}
	/**
	 * 设置带有效时间的对象到redis中
	 * @param key redis key
	 * @param value 值
	 * @param validTime 有效时间
	 * @param timeUnit 时间单位
	 */
	public static void setObject(String key,Object value,long validTime,TimeUnit timeUnit){
		try{
			getRedisTemplate().opsForValue().set(key, value, validTime, TimeUnit.SECONDS);
		}catch(Exception e){
			logger.error("Set the object failed with effective time redis,key="+key+"  value="+JSON.toJSONString(value)+"  validTime="+validTime+"  timeUnit="+JSON.toJSONString(timeUnit),e);
		}
	}
	/**
	 * 获取list集合的所有值
	 * @param key redis key
	 * @return
	 */
	public static List getListAll(String key){
		return getList(key,0,-1);
	}
	/**
	 * 获取指定下标的值，下标从0开始
	 * @param key redis key
	 * @param index 下标
	 * @return
	 */
	public static Object getList(String key,long index){
		try{
			return getRedisTemplate().opsForList().index(key,index);
		}catch(Exception e){
			logger.error("Failed to get list of specified values from redis,key="+key+"  index="+index,e);
		}
		return null;
	}
	/**
	 * 获取指定区间的list集合
	 * @param key redis key
	 * @param startIndex 开始下标，0表示第一个元素
	 * @param endIndex 结束下标 -1表示取到结尾
	 * @return
	 */
	public static List getList(String key,long startIndex,long endIndex){
		try{
			return getRedisTemplate().opsForList().range(key,startIndex,endIndex);
		}catch(Exception e){
			logger.error("Failed to get the list from redis,key="+key+"  startIndex="+startIndex+"  endIndex="+endIndex,e);
		}
		return null;
	}

	/**
	 * 从列表左边插入数据
	 * @param key redis key
	 * @param value
	 * @return
	 */
	public static Long leftPushList(String key,Object value){
		try{
			return getRedisTemplate().opsForList().leftPush(key,value);
		}catch(Exception e){
			logger.error("Redis the list on the left side insert the data failed,key="+key+"  value="+value,e);
		}
		return null;
	}

	/**
	 * 从列表左边插入一个list集合
	 * @param key redis key
	 * @param values
	 * @return
	 */
	public static Long leftPushListAll(String key,List values){
		try{
			return getRedisTemplate().opsForList().leftPushAll(key,values);
		}catch(Exception e){
			logger.error("Redis the list on the left side insert the data failed,key="+key+"  values="+JSON.toJSONString(values),e);
		}
		return null;
	}
	/**
	 * 从列表右边插入数据
	 * @param key redis key
	 * @param value
	 * @return
	 */
	public static Long rightPushList(String key,Object value){
		try{
			return getRedisTemplate().opsForList().rightPush(key,value);
		}catch(Exception e){
			logger.error("Redis the list on the right side insert the data failed,key="+key+"  value="+value,e);
		}
		return null;
	}

	/**
	 * 从列表右边插入一个list集合
	 * @param key redis key
	 * @param values
	 * @return
	 */
	public static Long rightPushListAll(String key,List values){
		try{
			return getRedisTemplate().opsForList().rightPushAll(key,values);
		}catch(Exception e){
			logger.error("Redis the list on the right side insert the data failed,key="+key+"  values="+JSON.toJSONString(values),e);
		}
		return -1L;
	}
	/**
	 * 删除列表中第一个与value匹配的值
	 * @param key redis key
	 * @param value
	 * @return
	 */
	public static Long removeFirstList(String key,Object value){
		return removeList(key,1,value);
	}
	/**
	 * 删除列表中最后一个与value匹配的值
	 * @param key redis key
	 * @param value
	 * @return
	 */
	public static Long removeLastList(String key,Object value){
		return removeList(key,-1,value);
	}
	/**
	 * 删除列表中所有与value相匹配的值
	 * @param key redis key
	 * @param value
	 * @return
	 */
	public static Long removeList(String key,Object value){
		return removeList(key,0,value);
	}
	/**
	 * 删除列表中指定的值
	 * @param key redis key
	 * @param count 大于0删除列表中第一个与value相匹配的值，
	 *               小于0删除列表中最后一个与value相匹配的值，
	 *               等于0删除列表中所有与value相匹配的值
	 * @param value
	 * @return
	 */
	private static Long removeList(String key,long count,Object value){
		try{
			return getRedisTemplate().opsForList().remove(key,count,value);
		}catch(Exception e){
			logger.error("List values redis delete failed,key="+key+"  count="+count+"  value="+value,e);
		}
		return null;
	}
	/**
	 * 判断Map Key 是否存在
	 * @param key map对象对应的redis key
	 * @param mapKey map的key
	 * @return true 表示存在，false 表示不存在
	 */
	public static boolean existsMapKey(String key,String mapKey){
		try{
			return getRedisTemplate().opsForHash().hasKey(key,mapKey);
		}catch(Exception e){
			logger.error("In the redis query whether there is a Map key fail,key="+key+"  mapKey="+mapKey,e);
		}
		return false;
	}


	/**
	 * 获取map值
	 * @param key map对象对应的redis key
	 * @param mapKey map的key
	 * @return
	 */
	public static Object getMapValue(String key,String mapKey){
		try{
			return getRedisTemplate().opsForHash().get(key,mapKey);
		}catch(Exception e){
			logger.error("Failed to get the values in the Map in the redis,key="+key+"  mapKey="+mapKey,e);
		}
		return null;
	}

	/**
	 * 获取map的多个值
	 * @param key map对象对应的redis key
	 * @param mapKeys map的key集合
	 * @return list 值的集合
	 */
	public static List getMultiMapValue(String key,List<String> mapKeys){
		try{
			return getRedisTemplate().opsForHash().multiGet(key,mapKeys);
		}catch(Exception e){
			logger.error("Failed to get multiple values in the Map in the redis,key="+key+"  mapKeys="+ JSON.toJSONString(mapKeys),e);
		}
		return null;
	}

	/**
	 * 获取map对象
	 * @param key map对象对应的redis key
	 * @return map
	 */
	public static Map<String,Object> getMapAll(String key){
		try{
			return getRedisTemplate().opsForHash().entries(key);
		}catch(Exception e){
			logger.error("Failed to get the Map of redis,key="+key,e);
		}
		return null;
	}

	/**
	 * 添加map
	 * @param key map对象对应的redis key
	 * @param mapKey map的key
	 * @param mapValue map的value
	 */
	public static void setMap(String key,String mapKey,Object mapValue){
		try{
			getRedisTemplate().opsForHash().put(key,mapKey,mapValue);
		}catch(Exception e){
			logger.error("Redis add Map failure,key="+key+"  mapValue="+JSON.toJSONString(mapValue),e);
		}
	}
	/**
	 * 添加map
	 * @param key map对象对应的redis key
	 * @param map map对象
	 */
	public static void setMapAll(String key, Map<String, Object> map){
		try{
			getRedisTemplate().opsForHash().putAll(key,map);
		}catch(Exception e){
			logger.error("Redis add Map failure,key="+key+"  map="+JSON.toJSONString(map),e);
		}
	}
	/**
	 * 删除单个map的key
	 * @param key map对象对应的redis key
	 * @param mapKey map的key
	 */
	public static void delMapKey(String key,String mapKey){
		try{
			getRedisTemplate().opsForHash().delete(key,mapKey);
		}catch(Exception e){
			logger.error("Redis to remove the Map key failure,key="+key+"  mapKey="+mapKey,e);
		}
	}
	/**
	 * 删除多个map key
	 * @param key map对象对应的redis key
	 * @param mapKeys map的key集合
	 */
	public static void delMapKey(String key,List<String> mapKeys){
		try{
			getRedisTemplate().opsForHash().delete(key,mapKeys);
		}catch(Exception e){
			logger.error("Redis to remove the Map multiple keys to fail,key="+key+"  mapKeys="+JSON.toJSONString(mapKeys),e);
		}
	}

	/**
	 * 获取无序集合所有元素
	 * @param key redis key
	 */
	public static Set getSetAll(String key){
		try{
			return getRedisTemplate().opsForSet().members(key);
		}catch(Exception e){
			logger.error("Failed to get unordered collection of all elements in the redis,key="+key,e);
		}
		return null;
	}

	/**
	 * 添加无序集合
	 * @param key redis key
	 */
	public static Long addSet(String key,Set values){
		try{
			return getRedisTemplate().opsForSet().add(key,values);
		}catch(Exception e){
			logger.error("Redis added unordered collection element fail,key="+key+"  values="+JSON.toJSONString(values),e);
		}
		return -1L;
	}
	/**
	 * 获取两个无序集合的交集
	 * @param key redis key
	 * @param otherKey 其他无序集合key
	 */
	public static Set getIntersectSet(String key,String otherKey){
		try{
			return getRedisTemplate().opsForSet().intersect(key,otherKey);
		}catch(Exception e){
			logger.error("Failed to get intersection redis,key="+key+"  otherKey="+otherKey,e);
		}
		return null;
	}
	/**
	 * 获取多个无序集合的交集
	 * @param key redis key
	 * @param otherKeys 其他无序集合key列表
	 */
	public static Set getIntersectSet(String key,List<String> otherKeys){
		try{
			return getRedisTemplate().opsForSet().intersect(key,otherKeys);
		}catch(Exception e){
			logger.error("Failed to get intersection redis,key="+key+"  otherKeys="+JSON.toJSONString(otherKeys),e);
		}
		return null;
	}

	/**
	 * 获取两个无序集合的并集
	 * @param key redis key
	 * @param otherKey 其他无序集合key
	 */
	public static Set getUnionSet(String key,String otherKey){
		try{
			return getRedisTemplate().opsForSet().union(key,otherKey);
		}catch(Exception e){
			logger.error("Failed to get unordered collection union redis,key="+key+"  otherKey="+otherKey,e);
		}
		return null;
	}
	/**
	 * 获取多个无序集合的并集
	 * @param key redis key
	 * @param otherKeys 其他无序集合key列表
	 */
	public static Set getUnionSet(String key,List<String> otherKeys){
		try{
			return getRedisTemplate().opsForSet().union(key,otherKeys);
		}catch(Exception e){
			logger.error("Failed to get unordered collection union redis,key="+key+"  otherKeys="+JSON.toJSONString(otherKeys),e);
		}
		return null;
	}

	/**
	 * 获取两个无序集合的差集
	 * @param key redis key
	 * @param otherKey 其他无序集合key
	 */
	public static Set getDifferenceSet(String key,String otherKey){
		try{
			return getRedisTemplate().opsForSet().difference(key,otherKey);
		}catch(Exception e){
			logger.error("Failed to get unordered collection difference sets redis,key="+key+"  otherKey="+otherKey,e);
		}
		return null;
	}
	/**
	 * 获取多个无序集合的差集
	 * @param key redis key
	 * @param otherKeys 其他无序集合key列表
	 */
	public static Set getDifferenceSet(String key,List<String> otherKeys){
		try{
			return getRedisTemplate().opsForSet().difference(key,otherKeys);
		}catch(Exception e){
			logger.error("Failed to get unordered collection difference sets redis,key="+key+"  otherKeys="+JSON.toJSONString(otherKeys),e);
		}
		return null;
	}

	/**
	 * 删除无序集合指定元素
	 * @param key redis key
	 * @param values 要删除的元素
	 */
	public static Long delSet(String key,Set values){
		try{
			return getRedisTemplate().opsForSet().add(key,values);
		}catch(Exception e){
			logger.error("Redis removed unordered collection specified element failure,key="+key+"  values="+JSON.toJSONString(values),e);
		}
		return -1L;
	}

	/**
	 * 获取有序集合范围内的结果集(从小到大）正序
	 * @param key redis key
	 * @return
	 */
	public static Set getRangeZsetAll(String key){
		return getRangeZset(key,0,-1);
	}
	/**
	 * 获取有序集合指定范围内的结果集(从小到大）正序
	 * @param key redis key
	 * @param startIndex 开始下标 下标从0开始
	 * @param endIndex  结束下标  下标-1结束
	 * @return
	 */
	public static Set getRangeZset(String key,long startIndex,long endIndex){
		try{
			return getRedisTemplate().opsForZSet().range(key,startIndex,endIndex);
		}catch(Exception e){
			logger.error("Redis failed to get an ordered set specified within the scope of the result set,key="+key+"  startIndex="+startIndex+"  endIndex="+endIndex,e);
		}
		return null;
	}

	/**
	 * 获取有序集合范围内的结果集(从大到小）倒叙
	 * @param key redis key
	 * @return
	 */
	public static Set getReverseRangeZsetAll(String key){
		return getReverseRangeZset(key,0,-1);
	}
	/**
	 * 获取有序集合指定范围内的结果集(从大到小）倒叙
	 * @param key redis key
	 * @param startIndex 开始下标 下标从0开始
	 * @param endIndex  结束下标  下标-1结束
	 * @return
	 */
	public static Set getReverseRangeZset(String key,long startIndex,long endIndex){
		try{
			return getRedisTemplate().opsForZSet().reverseRange(key,startIndex,endIndex);
		}catch(Exception e){
			logger.error("Redis failed to get an ordered set specified within the scope of the result set,key="+key+"  startIndex="+startIndex+"  endIndex="+endIndex,e);
		}
		return null;
	}

	/**
	 * 获取有序集合成员数
	 * @param key redis key
	 * @return
	 */
	public static Long getCountZset(String key){
		try{
			return getRedisTemplate().opsForZSet().zCard(key);
		}catch(Exception e){
			logger.error("Failed to get an ordered set member count,key="+key,e);
		}
		return -1L;
	}

	/**
	 * 添加有序集合，存在返回false，不存在返回true
	 * @param key redis key
	 * @param value 值
	 * @param score 分数
	 * @return
	 */
	public Boolean addZset(String key,Object value,double score){
		try{
			return getRedisTemplate().opsForZSet().add(key,value,score);
		}catch(Exception e){
			logger.error("Add an ordered set of failure,key="+key+"  value="+JSON.toJSONString(value)+"  score="+score,e);
		}
		return null;
	}
	/**
	 * 删除指定范围内的成员
	 * @param key redis key
	 * @param startIndex 开始下标 下标从0开始
	 * @param endIndex  结束下标  下标-1结束
	 * @return
	 */
	public static Long removeRangeZset(String key,long startIndex,long endIndex){
		try{
			return getRedisTemplate().opsForZSet().removeRange(key,startIndex,endIndex);
		}catch(Exception e){
			logger.error("To delete an ordered set members fail,key="+key+"  startIndex="+startIndex+"  endIndex="+endIndex,e);
		}
		return -1L;
	}
	/**
	 * 删除指定的成员
	 * @param key redis key
	 * @param values 要删除的成员
	 * @return
	 */
	public static Long removeZset(String key,List values){
		try{
			return getRedisTemplate().opsForZSet().remove(key,values);
		}catch(Exception e){
			logger.error("To delete an ordered set members fail,key="+key+"  values="+JSON.toJSONString(values),e);
		}
		return -1L;
	}


	/**
	 * 根据key删除redis中的对象
	 * @param key redis key
	 */
	public static void delKey(String key){
		try{
			getRedisTemplate().delete(key);
		}catch(Exception e){
			logger.error("Redis deleted object failed,key="+key,e);
		}
	}


	@Bean
	public RedisTemplate initRedisTemplate(RedisTemplate redisTemplate) {
		StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(stringRedisSerializer);
		redisTemplate.setHashKeySerializer(stringRedisSerializer);
		RedisUtil.redisTemplate = redisTemplate;
        return redisTemplate;
	}
}
